package com.tongji.diy.model.furniturePlacementOptimization.assembleComplement
{
	import com.tongji.diy.utils.OptimizationMath;
	
	import flash.geom.Matrix;
	import flash.geom.Point;

	public class FurnitureBase
	{
		private var _length:Number = 0;
		private var _width:Number = 0;
		private var _height:Number = 0;
		
		private var _angle:Number = 0;
		
		private var _x:Number = 0;
		private var _y:Number = 0;
		private var _z:Number = 0;
		
		private var _minX:Number = Infinity;
		private var _minY:Number = Infinity;
		private var _maxX:Number = -Infinity;
		private var _maxY:Number = -Infinity;
		
		//for accessible box
		private var _accminX:Number = Infinity;
		private var _accminY:Number = Infinity;
		private var _accmaxX:Number = -Infinity;
		private var _accmaxY:Number = -Infinity;
		
		private var _furnitureClass:int = -1;
		private var _furnitureIndex:int = -1;
		
		//每个家具的权重，该权重在家具迭代的过程中使用
		private var _weight:Number = 1;
		
		private var _anganistWall:Boolean = false;
		//与位置（x，y）有关
		private var _boundingBox:Vector.<Point> = new Vector.<Point>;
		//在这里没有进一步做实现，只是提供派生类的公共接口
		protected var _accessibleBox:Vector.<Point> = new Vector.<Point>;
		
	
		//private var _iteraDirection:Vector3D = new Vector3D(0,0,0);
		
		public function FurnitureBase(furnitrueIndex:int, furnitureClass:int, aganistWall:Boolean, length:Number = 0, width:Number = 0, height:Number = 0)
		{
			_length = length;
			_width = width;
			_height = height;
			_furnitureClass = furnitureClass;
			_furnitureIndex = furnitrueIndex;
			_anganistWall = aganistWall;
			_boundingBox = buildOBB(_x,_y,width,length);
		}

		
		protected function buildAccessOBB(Newx:Number, Newy:Number, Newwidth:Number, Newlength:Number):Vector.<Point>
		{
			_accminX = Infinity;
			_accminY = Infinity;
			_accmaxX = -Infinity;
			_accmaxY = -Infinity;
		
			var AABB:Vector.<Point> = new Vector.<Point>;
			var leftTop:Point = new Point(Newx - Newwidth/2, Newy + Newlength/2);
			AABB.push(leftTop);
			var rightTop:Point = new Point(Newx + Newwidth/2, Newy + Newlength/2);
			AABB.push(rightTop);
			var rightBottom:Point = new Point(Newx + Newwidth/2, Newy - Newlength/2);
			AABB.push(rightBottom);
			var leftBottom:Point = new Point(Newx - Newwidth/2, Newy - Newlength/2);
			AABB.push(leftBottom);
			
			var moveM1:Matrix = new Matrix();
			moveM1.translate(-x, -y);
			var moveM2:Matrix = new Matrix();
			moveM2.translate(x, y);
			var rotateM:Matrix = new Matrix();
			rotateM.rotate(-angle);
			moveM1.concat(rotateM);
			moveM1.concat(moveM2);
			var transM:Matrix = moveM1;
			
			for(var i:int = 0; i < AABB.length; ++i)
			{
				AABB[i] = transM.transformPoint(AABB[i]);
				if(_accmaxX < AABB[i].x)
					_accmaxX = AABB[i].x;
				if(_accminX > AABB[i].x)
					_accminX = AABB[i].x;
				if(_accmaxY < AABB[i].y)
					_accmaxY = AABB[i].y;
				if(_accminY > AABB[i].y)
					_accminY = AABB[i].y;
			}
			
			return AABB;
		}
		
		private function buildOBB(Newx:Number, Newy:Number, Newwidth:Number, Newlength:Number):Vector.<Point>
		{
			_minX = Infinity;
			_minY = Infinity;
			_maxX = -Infinity;
			_maxY = -Infinity;
			
			
			var AABB:Vector.<Point> = new Vector.<Point>;
			var leftTop:Point = new Point(Newx - Newwidth/2, Newy + Newlength/2);
			AABB.push(leftTop);
			var rightTop:Point = new Point(Newx + Newwidth/2, Newy + Newlength/2);
			AABB.push(rightTop);
			var rightBottom:Point = new Point(Newx + Newwidth/2, Newy - Newlength/2);
			AABB.push(rightBottom);
			var leftBottom:Point = new Point(Newx - Newwidth/2, Newy - Newlength/2);
			AABB.push(leftBottom);
			
			var moveM1:Matrix = new Matrix();
			moveM1.translate(-Newx, -Newy);
			var moveM2:Matrix = new Matrix();
			moveM2.translate(Newx, Newy);
			var rotateM:Matrix = new Matrix();
			rotateM.rotate(-angle);
			moveM1.concat(rotateM);
			moveM1.concat(moveM2);
			var transM:Matrix = moveM1;
			
			for(var i:int = 0; i < AABB.length; ++i)
			{
				AABB[i] = transM.transformPoint(AABB[i]);
				if(_maxX < AABB[i].x)
					_maxX = AABB[i].x;
				if(_minX > AABB[i].x)
					_minX = AABB[i].x;
				if(_maxY < AABB[i].y)
					_maxY = AABB[i].y;
				if(_minY > AABB[i].y)
					_minY = AABB[i].y;
			}
			
			
			return AABB;
		}
		
		/*public function set length(length:Number):void
		{
			this._length = length;
		}
		public function set width(_width:Number):void
		{
			this._width = width;
		}
		public function set height(height:Number):void
		{
			this._height = height;
		}*/
		
		
		
		public function set x(NewX:Number):void
		{
			//this._lastPositionAngle.x = this._x ;
			this._x = NewX;
			_boundingBox = buildOBB(_x,y,width, length);
		}
		
		public function set y(NewY:Number):void
		{
			//this._lastPositionAngle.y = this._y ;
			this._y = NewY;
			_boundingBox = buildOBB(x,_y,width, length);
		}
		
		public function set z(NewZ:Number):void
		{
			this._z = NewZ;
		}
		
		public function set angle(NewAngle:Number):void
		{
			//this._lastPositionAngle.z = this._angle;
			this._angle = NewAngle;
			_boundingBox = buildOBB(_x,_y, width, length);
		}
		
		public function set location(location:Point):void
		{
			this._x = location.x;
			this._y = location.y;
			_boundingBox = buildOBB(_x,_y, width, length);
		}
		
		public function set weight(newWeight:Number):void
		{
			_weight = newWeight;
		}
		
		public function get anganistWall():Boolean
		{
			return _anganistWall;
		}
		
		public function get x():Number
		{
			return _x;
		}
		
		public function get y():Number
		{
			return _y;
		}
		
		public function get z():Number
		{
			return _z;
		}
		
		public function get location():Point
		{
			return new Point(_x,_y);
		}
		
		public function get angle():Number
		{
			return _angle;
		}
		
		public function get length():Number
		{
			return _length;
		}
		public function get width():Number
		{
			return _width;
		}
		public function get height():Number
		{
			return _height;
		}
		public function get furnitureClass():int
		{
			return _furnitureClass;
		}
		public function get furnitureIndex():int
		{
			return _furnitureIndex;
		}
		
		public function get boundingBox():Vector.<Point>
		{
			return _boundingBox;
		}
		
		public function get accessibleBox():Vector.<Point>
		{
			return _accessibleBox;
		}
		
		public function get minX():Number
		{
			return _minX;
		}
		
		public function get minY():Number
		{
			return _minY;
		}
		
		public function get maxX():Number
		{
			return _maxX;
		}
		
		public function get maxY():Number
		{
			return _maxY;
		}
		
		public function get accMinX():Number
		{
			OptimizationMath.assert(_accminX != Infinity);
			return _accminX;
		}
		
		public function get accMaxX():Number
		{
			OptimizationMath.assert(_accmaxX != -Infinity);
			return _accmaxX;
		}
		
		public function get accMinY():Number
		{
			OptimizationMath.assert(_accminY != Infinity);
			return _accminY;
		}
		
		public function get accMaxY():Number
		{
			OptimizationMath.assert(_accmaxY != -Infinity);
			return _accmaxY;
		}
		
		public function get accWidth():Number
		{
			OptimizationMath.assert(_accminX != Infinity);
			OptimizationMath.assert(_accmaxX != -Infinity);
			return _accmaxX - _accminX;
		}
		
		public function get accLength():Number
		{
			OptimizationMath.assert(_accminY != Infinity);
			OptimizationMath.assert(_accmaxY != -Infinity);
			return _accmaxY - _accminY;
		}
		
		public function get weight():Number
		{
			return _weight;
		}
		
		public function get accX():Number
		{
			return (accMaxX + accMinX)/2;
		}
		
		public function get accY():Number
		{
			return (accMaxY + accMinY)/2;
		}
	}
}